//
// Created by chao.li on 2023/10/20.
//

#ifndef SRC_DRAW_CASE_H
#define SRC_DRAW_CASE_H

#include "vec.h"
#include "color.h"
#include "image.h"
#include "fractal.h"
#include "LSystem/LParser.h"
#include "ifs/drawer_ifs.h"
#include "drawer_complex.h"
#include "drawer_newton.h"

std::string get_out_path(const int paramNum, const char** params)
{
    std::string out_path = "image.png";
    if (paramNum > 1)
    {
        out_path = params[1];
    }
    return out_path;
}

void draw_spiral()
{
    const auto aspect_ratio = 9 / 9.0;
    const int image_width = 900;
    const int image_height = static_cast<int>(image_width / aspect_ratio);

    auto img = std::make_shared<image>(image_width, image_height);
    fractal_rec frac;
    frac.set_image(img);
    frac.paint_color(color3(1,1,1));
    frac.set_paint(color3(0,0,1));

    frac.draw_spiral({300, 100}, 300, 0.98);
    img->output_png("../images/spiral.png");
}

void draw_koch()
{
    const auto aspect_ratio = 16 / 9.0;
    const int image_width = 1600;
    const int image_height = static_cast<int>(image_width / aspect_ratio);

    auto img = std::make_shared<image>(image_width, image_height);
    fractal_rec frac;
    frac.set_image(img);
    frac.paint_color(color3(1,1,1));
    frac.set_paint(color3(0,0,1));
    auto center = vec2(200, 200);
    frac.draw_koch(center, 1200);
    img->output_png("../images/koch.png");
}

void draw_gene(std::vector<double>&& gene, const std::string& path,
               int depth = -1, vec2 start = {100, 300}, double length = 1400)
{
    const auto aspect_ratio = 16 / 9.0;
    const int image_width = 1600;
    const int image_height = static_cast<int>(image_width / aspect_ratio);

    auto img = std::make_shared<image>(image_width, image_height);
    fractal_gene frac;
    frac.set_image(img);
    frac.paint_color(color3(1,1,1));

    fractal_unit::angle2radian(gene);

    frac.set_paint(const_color::red());
    auto scale = 1 / fractal_unit::get_unit_length(gene);
    std::cout<< "scale: " << scale <<std::endl;

    frac.draw_gene({70, 800}, 120, gene, scale, 0, 0);

    frac.set_paint(const_color::blue());
    frac.draw_box({50, 770}, {160, 90});
    frac.draw_gene(start, length, gene, scale, 0, depth);
    img->output_png(path);
}

void draw_gene(std::vector<std::pair<double, double>>&& gene, const std::string& path,
               int depth = -1, vec2 start = {100, 300}, double length = 1400, double min_step = 1)
{
    const auto aspect_ratio = 16 / 9.0;
    const int image_width = 1600;
    const int image_height = static_cast<int>(image_width / aspect_ratio);

    auto img = std::make_shared<image>(image_width, image_height);
    fractal_gene frac;
    frac.set_image(img);
    frac.paint_color(const_color::white());

    fractal_unit::angle2radian(gene);

    frac.set_paint(const_color::blue());
    frac.draw_box({50, 770}, {160, 90});

    frac.set_paint(const_color::red());
    auto scale = 1 / fractal_unit::get_unit_length(gene);
    std::cout<< "scale: " << scale <<std::endl;

    frac.draw_gene({70, 800}, 120, gene, scale, 0, 0);

    frac.set_paint(const_color::blue());
    frac.draw_gene(start, length, gene, scale, 0, depth, min_step);
    img->output_png(path);
}

void draw_genes()
{
    draw_gene({-15, 90, -150, 90,}, "../images/gene_1.5474.png");

    draw_gene({0, 90, 180, 90,}, "../images/gene_2.0000.png", 6);
    draw_gene({0, 90, -180, 90,}, "../images/gene_1.5850.png", 6);

    draw_gene({45, -90}, "../images/gene_2.000_2.png", 16, {550, 300}, 500);

    draw_gene({0.0,90.0,-90.0,-90.0,90.0,-90.0,90.0,90.0,-90.0,},
              "../images/gene_1.3652.png",
              4, {350, 500}, 1200);

    draw_gene({-30,120.0,-150.0,120.0,-150.0,120.0,},
              "../images/gene_1.7828.png",
              5, {350, 500}, 1200);

    draw_gene({6.5,45.0,-180.0,112.5,-45.0,-180.0,-112.5,},
              "../images/gene_1.4883.png",
              20, {350, 500}, 1200);

    draw_gene({{0.0,1.0},{90.0,1.0},{-90.0,1.0},{-90.0,2.0}, {90.0,1.0}, {90.0,1.0},{-90.0,1.0},},
              "../images/gene_x_1.png",
              -1, {350, 500}, 1100, 4);

    draw_gene({{63.4,1.0},{-90.0,2.0},},
              "../images/gene_x_2.png",
              -1, {600, 300}, 500);

    draw_gene({{0.0,1.0},{85.0,1.0},{-170.0,1.0},{85.0,2.0},},
              "../images/gene_x_3.png",
              -1, {300, 300}, 1200);

    draw_gene({{15,2.0},{90.0,1.0},{150.0,1.0},{90.0,2.0},},
              "../images/gene_x_4.png",
              -1, {300, 300}, 1200);

    draw_gene({{0.0,0.6}, {80.0,1.0}, {-180.0,1.0}, {20.0,1.0},
               {-180.0,1.0},{-100.0,0.55},{80.0,0.9},{-180.0,0.9},
               {20.0,0.9},{-180.0,0.9},{-100.0,0.5},{80.0,0.8},
               {-180.0,0.8},{20.0,0.8}, {-180.0,0.8},{-100.0,0.45},
               {80.0,0.7},{-180.0,0.7},{20.0,0.7}, {-180.0,0.7},
               {-100.0,0.4},{80.0,0.6},{-180.0,0.6},{20.0,0.6},
               {-180.0,0.6},{-100.0,0.35},{80.0,0.5},{-180.0,0.5},
               {20.0,0.5}, {-180.0,0.5}, {-100.0,0.3},{80.0,0.4},
               {-180.0,0.4},{20.0,0.4}, {-180.0,0.4},{-100.0,0.25},
               {80.0,0.3},{-180.0,0.3},{20.0,0.3}, {-180.0,0.3},
               {-100.0,0.2},{80.0,0.2},{-180.0,0.2},{20.0,0.2},
               {-180.0,0.2},{-100.0,0.15},{80.0,0.1},{-180.0,0.1},
               {20.0,0.1}, {-180.0,0.1},{-100.0,0.1},},
              "../images/gene_x_5.png",
              -1, {300, 450}, 1200);

    draw_gene({{45,1.0},{-90.0,-1.0},},
              "../images/gene_y_1.png",
              -1, {500, 300}, 800, 1);

    draw_gene({{60.0,-1.0},{-60.0,1.0},{-60.0,-1.0},},
              "../images/gene_y_2.png",
              -1, {400, 100}, 800, 1);
}

void draw_fix(vec2 start, vec2 end,
              double scale, double radian, bool flip1, bool flip2,
              const std::string& path)
{
    const auto aspect_ratio = 16 / 9.0;
    const int image_width = 1600;
    const int image_height = static_cast<int>(image_width / aspect_ratio);

    auto img = std::make_shared<image>(image_width, image_height);
    fractal_fix frac;
    frac.set_image(img);
    frac.paint_color(const_color::white());

    frac.set_paint(flip1 || flip2 ? const_color::red() : const_color::blue());

    std::cout<< "scale: " << scale <<std::endl;
    frac.draw_fix(start, end, radian, scale, 1, flip1, flip2);
    img->output_png(path);
}

void draw_fixes()
{
    auto scale = 2 / sqrt(5);
    auto radian = std::atan2(1, 2);
    draw_fix({600, 300}, {1100, 300}, scale, radian, false, false,
             "../images/gene_f_1.png");

    draw_fix({600, 300}, {1100, 300}, scale, radian, false, true,
             "../images/gene_f_2.png");

    scale = 1 / std::sqrt(3);
    radian = drawer_basic::PI / 6;

    draw_fix({100, 300}, {1500, 300}, scale, radian, true, true,
             "../images/gene_f_koch.png");
}

void draw_map(const vec2& start,
              double n_br, double n_st, double s_st, double r_st,
              double length, double scale,
              double min_step, int depth,
              const std::string& path)
{
    const auto aspect_ratio = 16 / 9.0;
    const int image_width = 1600;
    const int image_height = static_cast<int>(image_width / aspect_ratio);

    auto img = std::make_shared<image>(image_width, image_height);
    fractal_map frac;
    frac.set_image(img);
    frac.paint_color(const_color::white());

    frac.set_paint(const_color::blue());
    frac.draw_map(start, n_br, n_st, s_st, r_st, length, scale, min_step, depth);
    img->output_png(path);
}

void draw_maps()
{
    draw_map({800, 450}, 6, 1, 1, 0, 200, 1.0f / (2 * 1.5),
             1, 5,
             "../images/map_6_1_5.png");

    draw_map({800, 450}, 6, 2, 1, 0, 200, 1.0f / (4),
             1, -4,
             "../images/map_6_2_4.png");

    draw_map({800, 450}, 5, 3, 0.8, drawer_basic::PI / 6, 200, 1.0f / (8),
             1, -5,
             "../images/map_5_3_5.png");

    draw_map({800, 450}, 8, 8, 0.6, drawer_basic::PI * 25 / 180, 200, 1.0f / (7),
             1, 4,
             "../images/map_8_8_5.png");

    draw_map({800, 450}, 6, 1, 1, 0, 20, 0.2,
             1, 3,
             "../images/map_372_a.png");

    draw_map({800, 450}, 6, 2, 1, 0, 200, 0.2,
             1, 4,
             "../images/map_372_b.png");

    draw_map({800, 450}, 5, 3, 5.0f / 6, drawer_basic::PI / 20, 200, 0.2,
             1, 5,
             "../images/map_373_b.png");
}

void draw_rainbow()
{
    const auto aspect_ratio = 16 / 9.0;
    const int image_width = 800;
    const int image_height = static_cast<int>(image_width / aspect_ratio);

    auto img = std::make_shared<image>(image_width, image_height);
    drawer_basic frac;
    frac.set_image(img);
    frac.paint_color(const_color::white());

    for (int i = 0; i < image_width; ++i) {
        frac.draw_line({i, 0}, 450, frac.PI / 2, double(i) / image_width);
    }
    img->output_png("../images/rainbow.png");

//    auto img2 = std::make_shared<image>2(image_width, image_width);
//
//    frac.set_image(&img2);
    frac.paint_color(const_color::black());

    auto calculate_color = [&frac](vec2 p0, vec2 p1, double length, double v) {
        vec2 dist = p1 - p0;
        auto h = (atan2(dist.y, dist.x) / drawer_basic::PI) / 2 + 0.5;
        auto s = dist.length() / length;
        return frac.hsv_to_rgb(color3(h, s, v));
    };

    auto draw_line = [&calculate_color, &frac](vec2 left, vec2 center, double length, double v){
        auto right = center.x * 2 - left.x;
        for (int i = left.x; i <= right; ++i) {
            auto color = calculate_color({i, left.y}, center, length, v);
            frac.draw_point({i, left.y}, color);
        }
    };

    auto draw_plate = [&draw_line](vec2 p, double length, double v){
        double r2 = length * length;
        draw_line({p.x-length, p.y}, p, length, v);
        for (int t = 1; t <= length; ++t) {
            double xx = sqrt(r2 - t * t);
//            xx = length;
            draw_line({p.x - xx, p.y + t}, p, length, v);
            draw_line({p.x - xx, p.y - t}, p, length, v);
        }
    };

    int num = 4, size = image_width / num;
    for (int i = 0; i < num; ++i) {
        for (int j = 0; j < num; ++j) {
            int ctx = size * i + size / 2;
            int cty = size * j + size / 2;
            draw_plate({ctx, cty}, size / 2 - 5, double(i + j * num + 0.5f) / (num * num));
        }
    }
    img->output_png("../images/color_plate.png");
}

void draw_basic()
{
    const auto aspect_ratio = 16 / 9.0;
    const int image_width = 1600;
    const int image_height = image_width / aspect_ratio;

    auto img = std::make_shared<image>(image_width, image_height);
    drawer_basic frac;
    frac.set_image(img);
    frac.paint_color(const_color::white());

    frac.set_paint(const_color::red());

    frac.fill_circle({10, 200}, 1);
    frac.fill_circle({20, 200}, 2);
    frac.fill_circle({30, 200}, 3);
    frac.fill_circle({40, 200}, 4);
    frac.fill_circle({60, 200}, 5);
    frac.fill_circle({80, 200}, 6);
    frac.fill_circle({180, 200}, 50);

    std::vector<vec2> points;
    auto center = vec2(10, 30);
    for (int i = 0; i < 5; ++i) {
        auto theta1 = frac.PI * 2 * i / 5;
        auto theta2 = frac.PI * 2 * (i + 0.5) / 5;
        auto p1 = vec2(center + frac.get_direction(theta1) * 8);
        points.push_back(p1);
        p1 = vec2(center + frac.get_direction(theta2) * 4);
        points.push_back(p1);
    }

    frac.fill_polygon(points);

    frac.set_paint(const_color::blue());

    frac.draw_circle({10, 200}, 1);
    frac.draw_circle({20, 200}, 2);
    frac.draw_circle({30, 200}, 3);
    frac.draw_circle({40, 200}, 4);
    frac.draw_circle({60, 200}, 5);
    frac.draw_circle({80, 200}, 6);
    frac.draw_circle({180, 200}, 50);

    frac.draw_polygon(points);

    int count = 16;
    points.resize(count);
    center = vec2(100,100);
    for (int i = 0; i < count; ++i) {
        frac.draw_line(center, 10, frac.PI * 2 / 16 * i);
    }
    frac.draw_circle({50, 100}, 10);

    points.resize(6);
    points[0] = {5, 1};
    points[1] = {10, 3};
    points[2] = {8, 11};
    points[3] = {5, 5};
    points[4] = {2, 7};
    points[5] = {2, 2};
    frac.fill_polygon(points);

    points.resize(4);
    points[0] = {20, 30};
    points[1] = {20, 10};
    points[2] = {30,10};
    points[3] = {30,30};
    frac.fill_polygon(points);
    frac.set_paint(const_color::red());
    frac.draw_polygon(points);

    img->output_png("../images/basic_test.png");

}


void draw_l_sys(){
    const auto aspect_ratio = 16 / 16.0;
    const int image_width = 900;
    const int image_height = image_width / aspect_ratio;

    auto p_img = std::make_shared<image>(image_width, image_height);

    l_sys::l_mac machine;

    // 雪花
    machine.process("../data/Koch1.l");
    machine.execute(5);
    machine.set_image(p_img);
    machine.paint_color(const_color::white());
    machine.set_paint(const_color::blue());
    machine.draw({200, 600}, 2);
    p_img->output_png("../images/l-system/Koch1.png");

    // 四方内生树
    p_img = std::make_shared<image>(2000, 2000);
    machine.set_image(p_img);
    machine.process("../data/FourTreeTest.l");
    machine.execute(6);
    machine.paint_color(const_color::white());
    machine.draw({200, 1800}, 2);
    p_img->output_png("../images/l-system/FourTreeTest.png");

    // 希尔伯特曲线
    p_img = std::make_shared<image>(900, 900);
    machine.set_image(p_img);
    machine.process("../data/Hilbert.l");
    machine.execute(7);
    machine.paint_color(const_color::white());
    machine.draw({100, 100}, 5);
    p_img->output_png("../images/l-system/Hilbert.png");

    // 分形龙
    p_img = std::make_shared<image>(900, 900);
    machine.set_image(p_img);
    machine.process("../data/LiuDragon.l");
    machine.execute(11);
    machine.paint_color(const_color::white());
    machine.draw({300, 300}, 6);
    p_img->output_png("../images/l-system/LiuDragon.png");

    // 植物
    p_img = std::make_shared<image>(900, 900);
    machine.set_image(p_img);
    machine.process("../data/HerbPlant.l");
    machine.execute(5);
    machine.paint_color(const_color::white());
    machine.draw({10, 450}, 6);
    p_img->output_png("../images/l-system/HerbPlant.png");

    // 侧柏
    p_img = std::make_shared<image>(900, 900);
    machine.set_image(p_img);
    machine.process("../data/OriArbo.l");
    machine.execute(5);
    machine.paint_color(const_color::white());
    machine.draw({10, 10}, 15, 45);
    p_img->output_png("../images/l-system/OriArbo.png");

    // final grass!!
//    p_img = std::make_shared<image>(900, 900);
//    machine.set_image(p_img);

    auto col1 = linear_to_gamma(color3{214, 219, 174} / 255);
    auto col2 = linear_to_gamma(color3{247, 248, 241} / 255);
    auto col3 = linear_to_gamma(color3{133, 144, 67} / 255);

    machine.draw_gradient(col1, col1, col2, col2);

    machine.set_paint(col3);
    machine.process("../data/grass.l");
    machine.execute(6);
    machine.draw(vec2{250, -100}, 3, 80);
    p_img->output_png("../images/l-system/grass.png");
}

void draw_uv()
{
    auto p_img = std::make_shared<image>(900, 900);
    drawer_basic drawer;
    drawer.set_image(p_img);
    drawer.draw_uv();
    p_img->output_png("../images/uv.png");

    auto col1 = linear_to_gamma({0.8392, 0.8588, 0.6824});
    auto col2 = linear_to_gamma({0.9689, 0.9725, 0.9450});

    drawer.draw_gradient(col1, col1, col2, col2);
    p_img->output_png("../images/gradient1.png");

    drawer.draw_gradient(col1, col2, col1, col2);
    p_img->output_png("../images/gradient2.png");

}

void draw_ifs()
{
    auto p_img = std::make_shared<image>(900, 900);
    ifs::drawer_ifs drawer;
    drawer.init_rule<ifs::ifs_rule_linear>({
        {{0,    0,      0,      0.16,   0,  0},     0.01},
        {{0.85, 0.04,   -0.04,  0.85,   0,  1.6},   0.85},
        {{0.2,  -0.26,  0.23,   0.22,   0,  1.6},   0.07},
        {{-0.15,0.28,   0.26,   0.24,   0,  0.44},  0.07},
    });
    drawer.set_image(p_img);

    auto col1 = linear_to_gamma(color3{214, 219, 174} / 255);
    auto col2 = linear_to_gamma(color3{247, 248, 241} / 255);
    auto col3 = linear_to_gamma(color3{133, 144, 67} / 255);

    drawer.draw_gradient(col1, col1, col2, col2);
    drawer.set_paint(col3);

    drawer.draw({0, 0}, 1000000, {400, 20}, {80, 80});
    p_img->output_png("../images/ifs/cai.png");


    auto c = 0.255, r = 0.75, q = 0.625,
        phi = -drawer_basic::PI / 8, psi = drawer_basic::PI / 5,
        aa = sin(phi), bb = cos(phi),
        mm = sin(psi), nn = cos(psi);

    drawer.init_rule<ifs::ifs_rule_linear>({
        {{c,    0,      0,      c,      2 / 3.0,        0},              1/3.0},
        {{r*bb, -r*aa,  r*aa,   r*bb,   0.5-0.5*r*bb,   c-0.5*r*aa},     1/3.0},
        {{q*nn, -r*mm,  q*mm,   r*nn,   0.5-0.5*q*nn,   0.6*c-0.5*q*mm}, 1/3.0},
    });

    drawer.draw_gradient(col1, col1, col2, col2);

    drawer.set_paint(col3);
    drawer.draw({0, 0}, 1000000, {5, 100}, {800, 800});
    p_img->output_png("../images/ifs/tree_961.png");

    p_img = std::make_shared<image>(1600, 900);
    drawer.set_image(p_img);
    drawer.init_rule<ifs::ifs_rule_linear>({
       {{0.5, 0, 0, 0.5, 0, 0}, 0.25},
       {{0.5, 0, 0, 0.5, 2, 0}, 0.25},
       {{-0.4, 0, 1, 0.4, 0, 1},0.25},
       {{-0.5, 0, 0, 0.5, 2, 1},0.25},
    });
    drawer.draw_gradient(col1, col1, col2, col2);
    drawer.set_paint(col3);
    drawer.draw({0, 0}, 800000, {-100, 900}, {1200, -450}, 10);
    p_img->output_png("../images/ifs/mountain.png");
}

void draw_julia()
{
    drawer_complex drawer;
    auto p_img = std::make_shared<image>(900, 900);
    drawer.set_image(p_img);

    drawer.paint_color(const_color::white());
    drawer.draw_julia({-2, -2},
                      {2, 2},
                      {-0.6, 0},
                      drawer_complex::cycle_state::convergency);
    p_img->output_png("../images/complex/julia_-0.6_0_convergence.png");

    drawer.paint_color(const_color::white());
    drawer.draw_julia({-2, -2},
                      {2, 2},
                      {-1.1, 0},
                      2);
    p_img->output_png("../images/complex/julia_-1.1_0_cycle2.png");

    drawer.paint_color(const_color::white());
    drawer.draw_julia({-2, -2},
                      {2, 2},
                      {0, 0.6},
                      drawer_complex::cycle_state::convergency);
    p_img->output_png("../images/complex/julia_0_0.6_convergence.png");

    drawer.paint_color(const_color::white());
    drawer.draw_julia({-2, -2},
                      {2, 2},
                      {-0.1, 0.77},
                      3);
    p_img->output_png("../images/complex/julia_-0.1_0.77_cycle3.png");

    drawer.paint_color(const_color::white());
    drawer.draw_julia({-2, -2},
                      {2, 2},
                      {0.3, 0.5},
                      4);
    p_img->output_png("../images/complex/julia_0.3_0.5_cycle4.png");

    drawer.paint_color(const_color::white());
    drawer.draw_julia({-2, -2},
                      {2, 2},
                      {-0.52, 0.55},
                      5);
    p_img->output_png("../images/complex/julia_-0.52_0.55_cycle5.png");

    drawer.paint_color(const_color::white());
    drawer.draw_julia({-2, -2},
                      {2, 2},
                      {-1.15, 0.25},
                      6);
    p_img->output_png("../images/complex/julia_-1.15_0.25_cycle6.png");


    drawer.paint_color(const_color::white());
    drawer.draw_julia({-2, -2},
                      {2, 2},
                      {-0.37, 0.61},
                      8);
    p_img->output_png("../images/complex/julia_-0.37_0.61_cycle8.png");
}

void draw_mandelbrot()
{
    drawer_complex drawer;
    auto p_img = std::make_shared<image>(900, 900);
    drawer.set_image(p_img);

    drawer.MIN_DELTA = 1e-20;
    drawer.MAX_Z_VALUE = 100;
    drawer.MAX_ITER = 10000;

    vec2 center = {-0.5, 0};
    vec2 half_size = {1.5, 1.5};

    drawer.paint_color(const_color::white());
    drawer.start_timer();
    drawer.draw_mandelbrot(center-half_size,
                           center+half_size);
    drawer.end_timer();
    p_img->output_png("../images/complex/mandelbrot_c_-0.5_s_1.png");

    center = {-0.7452, 0.186};
    half_size = {0.1,0.1};
    drawer.paint_color(const_color::white());
    drawer.start_timer();
    drawer.draw_mandelbrot(center-half_size,
                           center+half_size);
    drawer.end_timer();
    p_img->output_png("../images/complex/mandelbrot_c_-0.7452_0.186_s_0.1.png");

    half_size = {0.01,0.01};
    drawer.paint_color(const_color::white());
    drawer.start_timer();
    drawer.draw_mandelbrot(center-half_size,
                           center+half_size);
    drawer.end_timer();
    p_img->output_png("../images/complex/mandelbrot_c_-0.7452_0.186_s_0.01.png");

    half_size = {0.001,0.001};
    drawer.paint_color(const_color::white());
    drawer.start_timer();
    drawer.draw_mandelbrot(center-half_size,
                           center+half_size);
    drawer.end_timer();
    p_img->output_png("../images/complex/mandelbrot_c_-0.7452_0.186_s_0.001.png");

    half_size = {0.0001,0.0001};
    drawer.paint_color(const_color::white());
    drawer.start_timer();
    drawer.draw_mandelbrot(center-half_size,
                           center+half_size);
    drawer.end_timer();
    p_img->output_png("../images/complex/mandelbrot_c_-0.7452_0.186_s_0.0001.png");
}

void draw_newton()
{
    auto fz = [](const complexd& z){
        return z * z * z - complexd(1);
    };

    auto dfz = [](const complexd& z){
        return complexd(3) * z * z;
    };


    auto fz4 = [](const complexd& z){
        return z * z * z *z - complexd(1);
    };

    auto dfz4 = [](const complexd& z){
        return complexd(4) * z * z * z;
    };


    auto fz5 = [](const complexd& z){
        return z * z * z * z * z - complexd(1);
    };

    auto dfz5 = [](const complexd& z){
        return complexd(5) * z * z * z * z;
    };

    drawer_newton drawer;

    auto p_img = std::make_shared<image>(900, 900);
    drawer.set_image(p_img);

    drawer.draw_root({-2, -2}, {2, 2}, fz, dfz);
    p_img->output_png("../images/newton/newton_root_z3-1.png");


    drawer.draw_root({-3, -3}, {3, 3}, fz4, dfz4);
    p_img->output_png("../images/newton/newton_root_z4-1.png");


    drawer.draw_root({-3, -3}, {3, 3}, fz5, dfz5);
    p_img->output_png("../images/newton/newton_root_z5-1.png");
}
#endif //SRC_DRAW_CASE_H
